﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace Game2048WithCSharp
{
    public partial class MainForm : Form
    {
        IUser userInterface;
        ILogic logicInterface;

        private bool isTaskRunning = false;

        private GameState gameState;
        public MainForm()
        {
            InitializeComponent();
            // for test
            logicInterface = new LogicController();
            UIInit();
            newGameButton.Click += OnNewGameButtonPress;

            NewGame();
        }
        private void UIInit()
        {
            int panelHeight = gamePanel.Height;
            int panelWidth = gamePanel.Width;
            int boardSize;
            if (panelWidth > panelHeight)
            {
                MagicConstUI.StartPos = new Point((panelWidth - panelHeight) / 2, 0);
                boardSize = panelHeight;
            } else
            {
                MagicConstUI.StartPos = new Point(0, (panelHeight - panelWidth) / 2);
                boardSize = panelWidth;
            }
            int cubeSize = boardSize / MagicConstUI.ChessBoardSize * 7 / 8;
            MagicConstUI.CubeSize = new Size(cubeSize, cubeSize);
            int paddingSize = boardSize / (MagicConstUI.ChessBoardSize + 1) / 8;
            MagicConstUI.Padding = new Size(paddingSize, paddingSize);
            userInterface = new UIController();
            userInterface.Init(new UIElements(
                currentScoreLabel, bestScoreLabel
                , victoryLabel, defeatLabel
                , uiUpdateTimer
                , gamePanel.Controls.Add, gamePanel.Controls.Remove
                , StartTask, EndTask
                ));
            chessBoardBackground.Location = MagicConstUI.StartPos;
            chessBoardBackground.Size = new Size(
                MagicConstUI.CubeSize.Width * MagicConstUI.ChessBoardSize
                + MagicConstUI.Padding.Width * (MagicConstUI.ChessBoardSize + 1),
                MagicConstUI.CubeSize.Height * MagicConstUI.ChessBoardSize
                + MagicConstUI.Padding.Height * (MagicConstUI.ChessBoardSize + 1));
            victoryLabel.Location = chessBoardBackground.Location;
            victoryLabel.Size = chessBoardBackground.Size;
            defeatLabel.Location = chessBoardBackground.Location;
            defeatLabel.Size = chessBoardBackground.Size;
            Label[] bgCubes = { bgCubeLabel_0, bgCubeLabel_1, bgCubeLabel_2,
                bgCubeLabel_3, bgCubeLabel_4, bgCubeLabel_5, bgCubeLabel_6,
                bgCubeLabel_7, bgCubeLabel_8, bgCubeLabel_9, bgCubeLabel_10,
                bgCubeLabel_11, bgCubeLabel_12, bgCubeLabel_13, bgCubeLabel_14,
                bgCubeLabel_15};
            for (int i = 0; i < bgCubes.Length; i++)
            {
                int x = i / MagicConstUI.ChessBoardSize;
                int y = i % MagicConstUI.ChessBoardSize;
                bgCubes[i].Location = new Point(
                    MagicConstUI.StartPos.X +
                    MagicConstUI.CubeSize.Width * x +
                    MagicConstUI.Padding.Width * (x + 1),
                    MagicConstUI.StartPos.Y +
                    MagicConstUI.CubeSize.Height * y +
                    MagicConstUI.Padding.Height * (y + 1)
                    );
                bgCubes[i].Size = MagicConstUI.CubeSize;
            }
        }
        void EndTask()
        {
            isTaskRunning = false;
        }
        void StartTask()
        {
            isTaskRunning = true;
        }
        void OnNewGameButtonPress(object sender, EventArgs e)
        {
            NewGame();
        }
        void OnKeyDown(Keys keyData)
        {
            if (isTaskRunning) return;
            if (gameState != GameState.Gaming)
                return;
            Direction direction;
            switch (keyData)
            {
                case Keys.Up: direction = Direction.Up;break;
                case Keys.Down: direction = Direction.Down;break;
                case Keys.Left: direction = Direction.Left;break;
                case Keys.Right: direction = Direction.Right;break;
                default: return;
            }

            int currentScore, bestScore;
            bool move;
            userInterface.MoveCubes(
                logicInterface.MoveCubes(
                    direction,
                    out gameState,
                    out currentScore,
                    out bestScore,
                    out move),
                gameState,
                currentScore,
                bestScore);
            if (gameState == GameState.Gaming)
            {
                userInterface.GenerateNewCube(
                    logicInterface.GenerateNewCube(
                        out gameState, move),
                    gameState);
            }
        }
        void NewGame()
        {
            int[,] chessBoard;
            int currentScore, bestScore;
            chessBoard = logicInterface.NewGame(out currentScore, out bestScore);
            userInterface.NewGame(chessBoard, currentScore, bestScore);
            gameState = GameState.Gaming;
            isTaskRunning = false;
        }
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Up || keyData == Keys.Down || keyData == Keys.Left || keyData == Keys.Right)
            {
                OnKeyDown(keyData);
                return false;
            }
            return base.ProcessDialogKey(keyData);
        }

    }
}
